package com.example.learn_spring_boot3.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.example.learn_spring_boot3.service.FileService;
import com.example.learn_spring_boot3.utils.ResponseData;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@Service
public class FileServiceImpl implements FileService {
    // 文件保存到那个目录
    static final String FILE_SAVE_DIR_NAME = "files";

    // 项目目录
    static final String USER_DIR = System.getProperty("user.dir");

    @Value("${serverUrl}")
    private String serverUrl;

    @Value("${server.port}")
    private String port;

    @Override
    public ResponseEntity<ResponseData<Object>> upload(MultipartFile file, String dir) throws IOException {
        if (dir == null || dir.isEmpty()) {
            return ResponseEntity.ok(ResponseData.error(500, "dir 参数不能为空", null));
        } else {
            // TODO 校验只能上传指定目录的文件

            // 原始文件名称
            String originalFilename = file.getOriginalFilename();
            // 文件名称(不带后缀名)
            String fileName = FileUtil.mainName(originalFilename);
            // 文件后缀名
            String extName = FileUtil.extName(originalFilename);
            // 文件上传的目录
            String fileDir = USER_DIR + File.separator + FILE_SAVE_DIR_NAME + File.separator + dir;
            // 创建目录
            File fileDirObj = new File(fileDir);
            if (!fileDirObj.exists()) {
                boolean mkdirs = fileDirObj.mkdirs();
                if (!mkdirs) throw new Error("目录创建失败");
            }

            // 新的文件名
            String uuid = IdUtil.simpleUUID();
            String saveFileName = fileName + "_" + uuid + "." + extName;
            File saveFile = new File(fileDir + File.separator + saveFileName);

            if (saveFile.exists()) {
                System.out.println("TODO 文件已经存在, 重新生成新的文件名");
            }

            System.out.println("saveFile: " + saveFile.getPath());
            // 将文件保存到指定的位置
            file.transferTo(saveFile);

            String fileDownloadUrl = "http://" +
                    this.serverUrl + ":" +
                    this.port + "/file/download/" +
                    dir + "/" + saveFileName;

            return ResponseEntity.ok(ResponseData.success(fileDownloadUrl));
        }
    }

    @Override
    public void download(String dir, String fileName, HttpServletResponse response) {
        String filePath = USER_DIR + File.separator + FILE_SAVE_DIR_NAME + File.separator + dir + File.separator + fileName;
        System.out.println("filePath = " + filePath);
        File file = new File(filePath);

        try {
            if (file.exists()) {
                byte[] bytes = FileUtil.readBytes(filePath);

                // 设置响应的内容类型为二进制流, 下载时指定
                // response.setContentType("application/octet-stream");
                // 设置文件大小, 会显示下载进度
                response.setContentLength(bytes.length);
                // 设置只能下载
                // response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getName(), StandardCharsets.UTF_8));

                // 如果浏览器支持则可以直接预览, 如: 图片, pdf等, 不支持则会下载
                response.addHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(file.getName(), StandardCharsets.UTF_8));

                // 创建输出流
                ServletOutputStream outputStream = response.getOutputStream();
                outputStream.write(bytes);
                outputStream.flush();
                outputStream.close();
            } else {
                response.sendError(403, "没有找到对应的资源");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
